module IHP.IDE.SchemaDesigner.Controller.Helper where

import IHP.ControllerPrelude
import IHP.IDE.SchemaDesigner.Types
import qualified IHP.IDE.SchemaDesigner.Parser as Parser
import qualified Text.Megaparsec as Megaparsec
import qualified IHP.IDE.SchemaDesigner.Compiler as SchemaCompiler
import IHP.IDE.SchemaDesigner.View.Schema.Error
import IHP.IDE.ToolServer.Helper.Controller

instance ParamReader PostgresType where
    readParameter byteString = case Megaparsec.runParser Parser.sqlType "" (cs byteString) of
        Left error -> Left (cs $ tshow error)
        Right result -> Right result

instance ParamReader Expression where
    readParameter byteString = case Megaparsec.runParser Parser.expression "" (cs byteString) of
        Left parserError -> Left (cs $ Megaparsec.errorBundlePretty parserError)
        Right result -> Right result

instance ParamReader [IndexColumn] where
    readParameter byteString = case Megaparsec.runParser Parser.parseIndexColumns "" (cs byteString) of
        Left parserError -> Left (cs $ Megaparsec.errorBundlePretty parserError)
        Right result -> Right result

readSchema ::
    ( ?context::ControllerContext
    , ?modelContext::ModelContext
    , ?theAction::controller
    ) => IO [Statement]
readSchema = Parser.parseSchemaSql >>= \case
        Left error -> do render ErrorView { error }; pure []
        Right statements -> pure statements

getSqlError :: IO (Maybe ByteString)
getSqlError = Parser.parseSchemaSql >>= \case
        Left error -> do pure (Just error)
        Right statements -> do pure Nothing

updateSchema ::
    ( ?context :: ControllerContext
    , ?modelContext::ModelContext
    , ?theAction::controller
    ) => ([Statement] -> [Statement]) -> IO ()
updateSchema updateFn = do
    statements <- readSchema
    let statements' = updateFn statements
    SchemaCompiler.writeSchema statements'
    markDatabaseNeedsMigration

getAllObjectNames :: [Statement] -> [Text]
getAllObjectNames = mapMaybe extractObjectName
    where
        extractObjectName (StatementCreateTable CreateTable { name }) = Just name
        extractObjectName CreateEnumType { name } = Just name
        extractObjectName _                       = Nothing

